package cc.bluemc.modules.generateCode.service.impl;

import java.beans.Transient;
import java.io.File;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import cc.bluemc.modules.generateCode.entity.ColumnBean;
import cc.bluemc.modules.generateCode.entity.FileStruct;
import cc.bluemc.modules.generateCode.entity.TableBean;
import cc.bluemc.modules.generateCode.service.GenerateServiceFactory;
import cc.bluemc.modules.generateCode.service.IGenerateTableService;

@Service
public class GenerateTableService  {
	private Log log = LogFactory.getLog(this.getClass());
	@Autowired
	private IGenerateTableService generateTableService;
	
	public FileStruct getFiles(String packDir) throws Exception{
		 File file = new File(packDir);
		 FileStruct fileStruct = new FileStruct(file);
		 return fileStruct;
	}
	
	public String createTbSql(FileStruct fileStruct){
		 List<TableBean> tables=parseBean(fileStruct);
		 String sql= generateTableService.createSql(tables);
		 log.info("生成sql:\n"+sql);
		return sql;
	}
	
	private List<TableBean> parseBean(FileStruct fileStruct){
		List<TableBean> list = new ArrayList<TableBean>();
		if(FileStruct.type_file.equals(fileStruct.getType())){
			String suffix = fileStruct.getSuffix();
			if(StringUtils.isNotBlank(suffix)&&"class".equals(suffix)){
				try {
					String path= fileStruct.getPath().replaceFirst("^(.*classes)", "");
					path=path.replace("\\", ".").replaceFirst("\\.", "");
					Class<?> clazz = Class.forName(path.replace(".class", ""));
					TableBean tableBean=parseBean(clazz);
					if(null!=tableBean)
						list.add(tableBean);
				} catch (Exception e) {
					log.error("类不存在", e);
				}
			}
		}else{
			for(FileStruct c:fileStruct.getChilds()){
				list.addAll(parseBean(c));
			}
		}
		
		return list;
		
	}
	@SuppressWarnings("unchecked")
	private TableBean parseBean(Class clazz) throws Exception{
		if(clazz.isAnnotationPresent(Table.class)||clazz.isAnnotationPresent(Entity.class)||clazz instanceof Serializable){
			TableBean tableBean = new TableBean();
			tableBean.setTableNameCapitalized(clazz.getSimpleName());
			String tableName = addDash(clazz.getSimpleName());
			tableBean.setTableName(tableName.replace("_entity", ""));
			
			Field[] fields = clazz.getDeclaredFields();
			ColumnBean columnBean; 
			for(Field f: fields){
				String fName = f.getName();
				Transient tran = f.getAnnotation(Transient.class);
				if(null==tran){
					Class<?> type = f.getType();
					String methodPrefix =type==boolean.class?"is":"get";
					Method method = clazz.getDeclaredMethod(methodPrefix+StringUtils.capitalize(fName));
					if(null!=method&& null==method.getAnnotation(Transient.class)){
						columnBean = new ColumnBean();
						columnBean.setColumnName(addDash(f.getName()));
						if(null!=method.getAnnotation(Id.class)){
							columnBean.setPriKey(true);
							tableBean.setPriKey(columnBean.getColumnName());
						}
						if(type== Long.class||type==Integer.class){
							columnBean.setColumnType("bigint(32)");
						}else if(type==Date.class){
							columnBean.setColumnType("datetime");
						}else if(type==Boolean.class){
							columnBean.setColumnType("int(32)");	
						}else if(type==Double.class){
							columnBean.setColumnType("numeric(65,2)");
						}else{
							columnBean.setColumnType("varchar(32)");
						}
						tableBean.addColumn(columnBean);
					}
				}
			}
			return tableBean;
		}
		return null;
	}
	private String addDash(String str){
		str= str.replaceAll("(\\B[A-Z])", "_$1");
		return str.toLowerCase();
	}
	public void setGenerateTableService(
			IGenerateTableService generateTableService) {
		this.generateTableService = GenerateServiceFactory.createGenerateTableService();
	}
}
